package com.whz.gateway.common.web;

import com.whz.gateway.common.util.GatewayJsonUtils;
import com.whz.generic.api.ApiResponseWrapper;
import com.whz.generic.api.ApiStatus;
import com.whz.generic.api.ResponseOrigin;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.BodyInserters.fromValue;

/**
 * @author whz
 */
@Slf4j
@Data
@Builder
@ApiModel("网关内统一请求响应")
public class GatewayResponseBody {
    @ApiModelProperty("业务代码")
    private int code;
    @ApiModelProperty("业务消息")
    private String message;
    @ApiModelProperty("出错的调用方法")
    private String method;
    @ApiModelProperty("出错的调用路径")
    private String path;
    @ApiModelProperty("错误消息")
    private String error;
    @ApiModelProperty("出错时间戳")
    private Long timestamp;
    @ApiModelProperty("用户请求Ip")
    private String remoteIp;

    public byte[] toByte() {
        return GatewayJsonUtils.toJsonByte(getTongyuResponse(ResponseOrigin.gateway));
    }


    public ApiResponseWrapper<GatewayResponseBody> getTongyuResponse(ResponseOrigin origin) {
        ApiResponseWrapper<GatewayResponseBody> response = new ApiResponseWrapper<>();
        response.setCode(code);
        response.setStatus(ApiStatus.FAILURE);
        response.setPayLoad(this);
        response.setError(StringUtils.hasText(error) ? error : "gateway catch error.");
        response.origin(origin.name());
        return response;
    }

    public Mono<Void> sendToResponse(final ServerHttpResponse response) {
        response.setStatusCode(getHttpStatus());
        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        return response.writeWith(Mono.just(response.bufferFactory().wrap(toByte())));
    }

    public Mono<ServerResponse> sendToResponse() {
        return ServerResponse
                .status(getHttpStatus())
                .contentType(MediaType.APPLICATION_JSON)
                .body(fromValue(this));
    }

    private HttpStatus getHttpStatus() {
        HttpStatus status = HttpStatus.resolve(code);
        if (status == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return status;
    }
}